/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.webuisubsystem.managedbean;

import assisisw.smartcal.entitysubsystem.Calendar;
import assisisw.smartcal.entitysubsystem.Event;
import assisisw.smartcal.entitysubsystem.IUserController;
import assisisw.smartcal.entitysubsystem.Notification;
import assisisw.smartcal.entitysubsystem.User;
import assisisw.smartcal.entitysubsystem.exceptions.user.UserNotRegisteredException;
import assisisw.smartcal.utilities.Configuration;
import assisisw.smartcal.utilities.Utilities;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;

/**
 *
 * @author Francesco
 */

@ManagedBean ( eager = true )
@Named ( value = "dashboardBean" )
@ViewScoped ()
public class DashboardBean implements Serializable
{
    
    // Instance Fields
    
    /***/
    @EJB
    private INotificationClientsEndpoint notificationClientsEndpoint ;
    
    /***/
    @EJB
    private IUserController userController ;
    
    /***/
    private List < Calendar > calendars ;
    
    /***/
    private List < Notification > notifications ;
    
    /***/
    private ScheduleModel scheduleModel ;
    
    /***/
    private User managedUser ;
  
    // Instance Methods
    
    /***/
    public DashboardBean () {}
    
    /**
     * @return
     */
    public List < Calendar > getCalendars () 
    {
        return calendars ;
    } 
    
    /**
     * @return
     */
    public List < Notification > getNotifications () 
    {
        return notifications ;
    }
    
    /**
     * @return
     */
    public ScheduleModel getScheduleModel () 
    {
        return scheduleModel ;
    }
    
    /**
     * @return
     */
    public User getManagedUser () 
    {
        return managedUser ;
    }
    
    /***/
    public void enterDashboard () 
    {
        String username ; 
        if ( Objects.isNull ( managedUser ) )
        {
            username = FacesContext.getCurrentInstance ().getAttributes().get("mail").toString () ;
            try 
            {
                calendars = new ArrayList <> ( 3 ) ;
                notifications = new ArrayList <> ( 10 ) ;
                scheduleModel = new DefaultScheduleModel () ;
                managedUser = userController.getUser ( username );
                loadCalendars () ;
                loadNotifications () ;
                loadEvents () ;
                notificationClientsEndpoint.register ( managedUser , this ) ;
            } 
            catch ( UserNotRegisteredException ex ) 
            {
                try 
                {
                    FacesContext.getCurrentInstance().getExternalContext().redirect ( Configuration.Page.UNKNOWN_ERROR.getValue () ) ;
                } 
                catch (IOException ioException ) 
                {
                    Utilities.pageMasterErrorManagement () ;
                }
            }
        }
    }

    /**
     * @return
     */
    public String exitDashboard () 
    {
        String res ;
        notificationClientsEndpoint.unregister ( managedUser ) ;
        res = Configuration.Page.INDEX.getValue () ;
        return res ;
    }
    
    /**
     * @param calendar 
     */
    public void onNewCalendarInserted ( Calendar calendar ) 
    {
        calendars.add ( calendar ) ;
        FacesContext.getCurrentInstance().addMessage ( null, new FacesMessage ( "Done !" , "New Calendar added correctly !" ) ) ; 
    }
    
    /**
     * @param calendar 
     */
    public void onCalendarUpdated ( Calendar calendar ) 
    {
        Event e ;
        calendars.set ( calendars.indexOf ( calendar ) , calendar ) ;
        if ( ! calendar.isVisible() ) 
            for ( ScheduleEvent s : scheduleModel.getEvents () )
            {
                e = (Event) s.getData();
                scheduleModel.deleteEvent(s);
            }
        RequestContext.getCurrentInstance().update("dashboardSchedule");
        FacesContext.getCurrentInstance().addMessage ( null , new FacesMessage ( "Done !" , "Calendar Correctly Updated !" ) );
    }

    /**
     * @param calendar 
     */
    public void onCalendarDeleted ( Calendar calendar ) 
    {
        calendars.remove ( calendar ) ;
        FacesContext.getCurrentInstance().addMessage 
            ( null , new FacesMessage ( "Done !" , "Calendar Correctly Deleted !" ) );
    }
    
    /**
     * @param event
     */
    public void onEventAdded ( Event event ) 
    {
        scheduleModel.addEvent ( new DefaultScheduleEvent ( event.getName () , event.getIniDate () , event.getEndDate () , event ) ) ;
        FacesContext.getCurrentInstance().addMessage 
            ( null , new FacesMessage ( "Done !" , "Event Correctly Added !" ) );
    }
    
    /**
     * @param updatedEvent  
     */
    public void onEventUpdated ( Event updatedEvent ) 
    {
        for ( ScheduleEvent s : scheduleModel.getEvents() )
            if ( s.getData().equals ( updatedEvent ) )
            {
                scheduleModel.deleteEvent(s);
                break ;
            }
        scheduleModel.addEvent ( new DefaultScheduleEvent ( updatedEvent.getName () , updatedEvent.getIniDate () , updatedEvent.getEndDate () , updatedEvent )  ) ;
        FacesContext.getCurrentInstance().addMessage 
            ( null , new FacesMessage ( "Done !" , "Event Correctly Updated !" ) );
        RequestContext.getCurrentInstance().update("dashboardSchedule");
    }
    
    /**
     * @param deletedEvent 
     */
    public void onEventDeleted ( Event deletedEvent ) 
    {
        for ( ScheduleEvent s : scheduleModel.getEvents() )
            if ( s.getData().equals ( deletedEvent ) )
            {
                scheduleModel.deleteEvent(s);
                break ;
            }
        FacesContext.getCurrentInstance().addMessage 
            ( null , new FacesMessage ( "Done !" , "Event Correctly Removed !" ) );
    }
    
    /**
     * @param notification 
     */
    public void onNotificationAdded ( Notification notification ) 
    {
        notifications.add ( notification ) ;
        updateNotificationsView(); 
    }
    
    public void onNotificationRemoved ( Notification notification )
    {
        notifications.remove(notification);
        updateNotificationsView();
    }
    
    /**
     * @param  selectEvent 
     * @return
     */
    public DefaultScheduleEvent onEventSelect ( SelectEvent selectEvent ) 
    {
        DefaultScheduleEvent selectedEvent ;
        selectedEvent = ( ( DefaultScheduleEvent ) selectEvent.getObject () ) ;
        return selectedEvent ;
    }
    
    /***/
    private void loadCalendars () 
    {
        for ( Calendar c : managedUser.getOwnedCalendars () )
            calendars.add(c);
        for ( Calendar c : managedUser.getSharedCalendars () )
            calendars.add ( c ) ;
    }
    
    /***/
    private void loadNotifications () 
    {
        for ( Notification n : managedUser.getNotifications () )
            if ( ! n.isAlreadyRead() )
                notifications.add ( n ) ;
    }
    
    /***/
    private void loadEvents () 
    {      
        DefaultScheduleEvent evt ;
        for ( Calendar c : managedUser.getOwnedCalendars() )
            if ( c.isVisible() )
                for ( Event e : c.getContainedEvents () )
                {
                    evt = new DefaultScheduleEvent ( e.getName () , e.getIniDate () , e.getEndDate () , e ) ;
                    scheduleModel.addEvent ( evt ) ;
                }
                for ( Calendar c : managedUser.getSharedCalendars () )
            for ( Event e : c.getContainedEvents() )
                if ( e.getVisibility().trim().compareToIgnoreCase ( Event.PUBLIC_VISIBILITY ) == 0 )
                    scheduleModel.addEvent ( new DefaultScheduleEvent ( e.getName () , e.getIniDate () , e.getEndDate () , e ) ) ;
                else
                    // set not editable
                    scheduleModel.addEvent ( new DefaultScheduleEvent ( "" , e.getIniDate () , e.getEndDate () , e ) ) ;                    
        for ( Event e : managedUser.getInvitedEvents () )
            scheduleModel.addEvent ( new DefaultScheduleEvent ( e.getName () , e.getIniDate () , e.getEndDate () , e ) ) ;
    }
    
    private void updateNotificationsView () 
    {
        RequestContext requestContext ;
        requestContext = RequestContext.getCurrentInstance () ;
        requestContext.update ( "dashboardRightBox" ) ;
    }
    
}
